﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Microsoft.Practices.Unity;
using Microsoft.Practices.ObjectBuilder2;

namespace cludg.Infrastructure.DI.Unity.Enumerable
{
	internal class EnumerableBuilderStrategy : BuilderStrategy
	{
		protected readonly IUnityContainer Container;

		public EnumerableBuilderStrategy(IUnityContainer container)
			: base()
		{
			Container = container;
		}

		public override void PreBuildUp(IBuilderContext context)
		{
			if (context.BuildKey is NamedTypeBuildKey)
			{
				NamedTypeBuildKey key = (NamedTypeBuildKey)context.BuildKey;
				if (String.IsNullOrEmpty(key.Name) && 
					key.Type.IsGenericType && 
					(key.Type.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
				{
					var genericArguments = key.Type.GetGenericArguments();
					if (genericArguments.Length == 1)
					{
						IEnumerable<object> implementations = Container.ResolveAll(genericArguments[0]);
						
						Type listType = typeof(List<>).MakeGenericType(genericArguments[0]);
						object list = listType.GetConstructor(Type.EmptyTypes).Invoke(null);

						MethodInfo add = listType.GetMethod("Add", new Type[] { genericArguments[0] });

						foreach (var impl in implementations)
							add.Invoke(list, new object[] { impl });

						context.Existing = list;
						context.BuildComplete = true;
					}
				}
			}
		}
	}
}
